<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html>
<head>
<title>Basic drawing in Cairo</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="cairo, graphics, C, 2D vector library, basic drawing, 
line, stroke, fill, dash, line cap, line join">
<meta name="description" content="In this chapter of the Cairo tutorial, we will
do some basic drawing.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Basic drawing in Cairo</h1>


<p>
In this part of the Cairo graphics tutorial, we will draw some basic primitives. 
We will draw simple lines, use fill and 
stroke operations, we will talk about dashes, line caps and line joins.
</p>

<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* NewSquare */
google_ad_slot = "0364418177";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script>

<h2>Lines</h2>

<p>
Lines are very basic vector objects. To draw a line, we use two function calls. 
The starting point is specified with the <code>cairo_move_to()</code> call. 
The ending point of a line is specified with the
<code>cairo_line_to()</code> call.
</p>

<pre class="code">
#include &lt;cairo.h&gt;
#include &lt;gtk/gtk.h&gt;

static void do_drawing(cairo_t *);

struct {
  int count;
  double coordx[100];
  double coordy[100];
} glob;

static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, 
    gpointer user_data)
{
  cr = gdk_cairo_create(gtk_widget_get_window(widget));
  do_drawing(cr);
  cairo_destroy(cr);

  return FALSE;
}

static void do_drawing(cairo_t *cr)
{
  cairo_set_source_rgb(cr, 0, 0, 0);
  cairo_set_line_width(cr, 0.5);

  int i, j;
  for (i = 0; i &lt;= glob.count - 1; i++ ) {
      for (j = 0; j &lt;= glob.count - 1; j++ ) {
          cairo_move_to(cr, glob.coordx[i], glob.coordy[i]);
          cairo_line_to(cr, glob.coordx[j], glob.coordy[j]);
      }
  }

  glob.count = 0;
  cairo_stroke(cr);    
}

static gboolean clicked(GtkWidget *widget, GdkEventButton *event,
    gpointer user_data)
{
    if (event->button == 1) {
        glob.coordx[glob.count] = event->x;
        glob.coordy[glob.count++] = event->y;
    }

    if (event->button == 3) {
        gtk_widget_queue_draw(widget);
    }

    return TRUE;
}


int main(int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *darea;
  
  glob.count = 0;

  gtk_init(&amp;argc, &amp;argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  darea = gtk_drawing_area_new();
  gtk_container_add(GTK_CONTAINER(window), darea);
 
  gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK);

  g_signal_connect(G_OBJECT(darea), "draw", 
      G_CALLBACK(on_draw_event), NULL); 
  g_signal_connect(window, "destroy",
      G_CALLBACK(gtk_main_quit), NULL);  
    
  g_signal_connect(window, "button-press-event", 
      G_CALLBACK(clicked), NULL);
 
  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 400, 300); 
  gtk_window_set_title(GTK_WINDOW(window), "Lines");

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}
</pre>

<p>
In our example, we click randomly on a window with a left mouse button. 
Each click is stored in an array. When we right click on the window, all 
points are connected with every point in the array. This way, we can create
some interesting objects. Right clicking on the drawn object clears the window, 
and we can click another object.
</p>

<pre class="explanation">
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_set_line_width (cr, 0.5);
</pre>

<p>
The lines will be drawn in black ink and will be 0.5 points wide.
</p>

<pre class="explanation">
int i, j;
for (i = 0; i &lt;= glob.count - 1; i++ ) {
    for (j = 0; j &lt;= glob.count - 1; j++ ) {
        cairo_move_to(cr, glob.coordx[i], glob.coordy[i]);
        cairo_line_to(cr, glob.coordx[j], glob.coordy[j]);
    }
}
</pre>

<p>
We connect every point from the array to every other point.
</p>

<pre class="explanation">
cairo_stroke(cr);
</pre>

<p>
The <code>cairo_stroke()</code> call draws the lines.
</p>


<pre class="explanation">
g_signal_connect(window, "button-press-event", 
    G_CALLBACK(clicked), NULL);
</pre>

<p>
We connect the <code>button-press-event</code> to the clicked callback.  
</p>

<pre class="explanation">
if (event->button == 1) {
    glob.coordx[glob.count] = event->x;
    glob.coordy[glob.count++] = event->y;
}
</pre>

<p>
Inside the clicked callback, we determine, if we there was a left or right click. 
If we click with a left mouse button, we store the x, y coordinates into the arrays. 
</p>

<pre class="explanation">
if (event->button == 3) {
    gtk_widget_queue_draw(widget);
}
</pre>

<p>
By right clicking, we redraw the window.
</p>

<img src="/img/gfx/cairoc/lines.png" alt="Lines">
<div class="figure">Figure: Lines</div>


<h2>Fill and stroke</h2>

<p>
The stroke operation draws the outlines of shapes and the fill 
operation fills the insides of shapes.
</p>

<pre class="code">
#include &lt;cairo.h&gt;
#include &lt;gtk/gtk.h&gt;
#include &lt;math.h&gt;

static void do_drawing(cairo_t *, GtkWidget *);

static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, 
    gpointer user_data)
{
  cr = gdk_cairo_create(gtk_widget_get_window(widget));
  do_drawing(cr, widget);
  cairo_destroy(cr);

  return FALSE;
}

static void do_drawing(cairo_t *cr, GtkWidget *widget)
{
  GtkWidget *win = gtk_widget_get_toplevel(widget);
  
  int width, height;
  gtk_window_get_size(GTK_WINDOW(win), &amp;width, &amp;height);
  
  cairo_set_line_width(cr, 9);  
  cairo_set_source_rgb(cr, 0.69, 0.19, 0);
  
  cairo_translate(cr, width/2, height/2);
  cairo_arc(cr, 0, 0, 50, 0, 2 * M_PI);
  cairo_stroke_preserve(cr);

  cairo_set_source_rgb(cr, 0.3, 0.4, 0.6); 
  cairo_fill(cr);      
}


int main (int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *darea;
  
  gtk_init(&amp;argc, &amp;argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  darea = gtk_drawing_area_new();
  gtk_container_add(GTK_CONTAINER(window), darea);

  g_signal_connect(G_OBJECT(darea), "draw", 
      G_CALLBACK(on_draw_event), NULL);
  g_signal_connect(G_OBJECT(window), "destroy",
      G_CALLBACK(gtk_main_quit), NULL);

  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 300, 200); 
  gtk_window_set_title(GTK_WINDOW(window), "Fill &amp; stroke");

  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}
</pre>

<p>
In our example, we will draw a circle and fill it with a solid color.
</p>

<pre class="explanation">
#include &lt;math.h&gt;
</pre>

<p>
This header file is needed for the <code>M_PI</code> constant.
</p>

<pre class="explanation">
GtkWidget *win = gtk_widget_get_toplevel(widget);

int width, height;
gtk_window_get_size(GTK_WINDOW(win), &amp;width, &amp;height);
</pre>

<p>
Here we get the width and height of the window. We will need these 
values, when we draw the circle. The circle will be resized, when we resize the window.
</p>

<pre class="explanation">
cairo_set_line_width(cr, 9);  
cairo_set_source_rgb(cr, 0.69, 0.19, 0);
</pre>

<p>
We set a line width with the <code>set_line_width()</code> method. We set the source to 
some dark red colour using the <code>set_source_rgb()</code> method.
</p>

<pre class="explanation">
cairo_translate(cr, width/2, height/2);
cairo_arc(cr, 0, 0, 50, 0, 2 * M_PI);
cairo_stroke_preserve(cr);
</pre>

<p>
With the <code>cairo_translate()</code> method, we move the drawing origin to the 
center of the window. We want our circle to be centered. The <code>arc()</code> method 
adds a new circular path to the cairo drawing context. Finally, the 
<code>stroke_preserve()</code> method draws the outline of the circle. Unlike 
the <code>stroke()</code> method, it also preserves the shape for later drawing.
</p>

<pre class="explanation">
cairo_set_source_rgb(cr, 0.3, 0.4, 0.6); 
cairo_fill(cr);
</pre>

<p>
Here we fill the cirle with blue color.
</p>

<img src="/img/gfx/cairoc/fillstroke.png" alt="Fill and stroke">
<div class="figure">Figure: Fill and stroke</div>


<h2>Pen dashes</h2>

<p>
Each line can be drawn with a different pen dash. It defines the style of the line. 
The dash is used by the <code>cairo_stroke()</code> function call.
The dash pattern is specified by the <code>cairo_set_dash()</code> function. 
The pattern is set by the dash array, which is an array of positive floating point values. 
They set the on and off parts of the dash pattern. We also specify the length of the 
array and the offset value. If the length is 0, the dashing is disabled. If it is 1, a 
symmetric pattern is asumed with alternating on and off portions of the size specified 
by the single value in dashes.
</p>

<pre class="code">
static void do_drawing(cairo_t *cr)
{
  cairo_set_source_rgba(cr, 0, 0, 0, 1);

  static const double dashed1[] = {4.0, 21.0, 2.0};
  static int len1  = sizeof(dashed1) / sizeof(dashed1[0]);

  static const double dashed2[] = {14.0, 6.0};
  static int len2  = sizeof(dashed2) / sizeof(dashed2[0]);

  static const double dashed3[] = {1.0};

  cairo_set_line_width(cr, 1.5);

  cairo_set_dash(cr, dashed1, len1, 0);

  cairo_move_to(cr, 40, 30);  
  cairo_line_to(cr, 200, 30);
  cairo_stroke(cr);

  cairo_set_dash(cr, dashed2, len2, 1);

  cairo_move_to(cr, 40, 50);  
  cairo_line_to(cr, 200, 50);
  cairo_stroke(cr);

  cairo_set_dash(cr, dashed3, 1, 0);

  cairo_move_to(cr, 40, 70);  
  cairo_line_to(cr, 200, 70);
  cairo_stroke(cr);  
}
</pre>

<p>
In this example, we will draw three lines with different dash patterns.
</p>

<pre class="explanation">
static const double dashed1[] = {4.0, 21.0, 2.0};
</pre>

<p>
We have a pattern of three numbers. We have 4 points drawn, 21 not drawn and 2 drawn. 
Then 4 points not drawn, 21 points drawn and 2 not drawn. This pattern takes 
turns until the end of the line.
</p>

<pre class="explanation">
static int len1  = sizeof(dashed1) / sizeof(dashed1[0]);
</pre>

<p>
We get the size of the array.
</p>

<pre class="explanation">
cairo_set_dash(cr, dashed1, len1, 0);
</pre>

<p>
We set the dash.
</p>


<pre class="explanation">
static const double dashed3[] = {1.0};
...
cairo_set_dash(cr, dashed3, 1, 0);

cairo_move_to(cr, 40, 70);  
cairo_line_to(cr, 200, 70);
cairo_stroke(cr);  
</pre>

<p>
These lines create a line with a pen dash of a symmetric pattern of alternating 
single on and off points.
</p>


<img src="/img/gfx/cairoc/dashes.png" alt="Dashes">
<div class="figure">Figure: Dashes</div>


<h2>Line caps</h2>

<p>
The line caps are endpoints of lines. 
</p>

<ul>
 <li>CAIRO_LINE_CAP_SQUARE</li> 
 <li>CAIRO_LINE_CAP_ROUND</li>
 <li>CAIRO_LINE_CAP_BUTT</li>
</ul>

<p>
There are three different line cap styles in Cairo.
</p>

<div class="center">
<img src="/img/gfx/cairoc/linecaps.png" alt="Line caps">
<div class="figure">Figure: Square, round and butt caps</div>
</div>

<p>
A line with a <code>CAIRO_LINE_CAP_SQUARE</code> cap will have a 
different size, than a line with a <code>CAIRO_LINE_CAP_BUTT</code> cap. 
If a line is width px wide, the line with a <code>CAIRO_LINE_CAP_SQUARE</code> 
cap will be exactly width px greater in size. width/2 px at the beginning and width/2 px at the end.
</p>

<pre class="code">
static void do_drawing(cairo_t *cr)
{
  cairo_set_line_width(cr, 10);

  cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT); 
  cairo_move_to(cr, 30, 50); 
  cairo_line_to(cr, 150, 50);
  cairo_stroke(cr);

  cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); 
  cairo_move_to(cr, 30, 90); 
  cairo_line_to(cr, 150, 90);
  cairo_stroke(cr);

  cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE); 
  cairo_move_to(cr, 30, 130); 
  cairo_line_to(cr, 150, 130);
  cairo_stroke(cr);

  cairo_set_line_width(cr, 1.5);

  cairo_move_to(cr, 30, 40);  
  cairo_line_to(cr, 30, 140);
  cairo_stroke(cr);

  cairo_move_to(cr, 150, 40);  
  cairo_line_to(cr, 150, 140);
  cairo_stroke(cr);

  cairo_move_to(cr, 155, 40);  
  cairo_line_to(cr, 155, 140);
  cairo_stroke(cr);    
}
</pre>

<p>
The example draws three lines with three different caps. It will also 
graphically demonstrate the differences is size of the lines.
</p>

<pre class="explanation">
cairo_set_line_width(cr, 10);
</pre>

<p>
Our lines will be 10 px wide.
</p>

<pre class="explanation">
cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); 
cairo_move_to(cr, 30, 90); 
cairo_line_to(cr, 150, 90);
cairo_stroke(cr);
</pre>

<p>
Here we draw a horizontal line with a <code>CAIRO_LINE_CAP_ROUND</code> cap.
</p>

<pre class="explanation">
cairo_set_line_width(cr, 1.5);

cairo_move_to(cr, 30, 40);  
cairo_line_to(cr, 30, 140);
cairo_stroke(cr);
</pre>

<p>
This is one of the three vertical lines used to demostrate the differences in size.
</p>

<img src="/img/gfx/cairoc/linecaps2.png" alt="Line caps">
<div class="figure">Figure: Line caps</div>


<h2>Line joins</h2>

<p>
The lines can be joined using three different join styles. 
</p>

<ul>
 <li>CAIRO_LINE_JOIN_MITER</li> 
 <li>CAIRO_LINE_JOIN_BEVEL</li>
 <li>CAIRO_LINE_JOIN_ROUND</li>
</ul>

<div class="center">
<img src="/img/gfx/cairoc/joins.jpg" alt="Bevel, Round, Miter line joins">
<div class="figure">Figure: Bevel, Round, Miter line joins</div>
</div>
<br>

<pre class="code">
static void do_drawing(cairo_t *cr)
{
  cairo_set_source_rgb(cr, 0.1, 0, 0);

  cairo_rectangle(cr, 30, 30, 100, 100);
  cairo_set_line_width(cr, 14);
  cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER); 
  cairo_stroke(cr);

  cairo_rectangle(cr, 160, 30, 100, 100);
  cairo_set_line_width(cr, 14);
  cairo_set_line_join(cr, CAIRO_LINE_JOIN_BEVEL); 
  cairo_stroke(cr);

  cairo_rectangle(cr, 100, 160, 100, 100);
  cairo_set_line_width(cr, 14);
  cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); 
  cairo_stroke(cr);    
}
</pre>

<p>
In this example, we draw three thick rectangles with various line joins. 
</p>

<pre class="explanation">
cairo_rectangle(cr, 30, 30, 100, 100);
cairo_set_line_width(cr, 14);
cairo_set_line_join(cr, CAIRO_LINE_JOIN_MITER); 
cairo_stroke(cr);
</pre>

<p>
In this code  example, we draw a rectangle with <code>CAIRO_LINE_JOIN_MITER</code> 
join style. The lines are 14 px wide. 
</p>

<img src="/img/gfx/cairoc/linejoins.png" alt="Line joins">
<div class="figure">Figure: Line joins</div>

<p>
In this chapter, we did some basic drawing. 
</p>


<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div>
<br>

<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>

<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified December 12, 2012  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>


